<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta
      name="viewport"
      content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"
    />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>cos-js-sdk-v5</title>
    <style>
      body {
        font-family: 'Microsoft YaHei';
      }
      .page {
        min-width: 1000px;
        margin: 0 auto;
        padding: 0 50px;
      }
      .main-wrap {
        float: left;
        width: 100%;
      }
      .main {
        margin-right: 700px;
        margin-bottom: 20px;
        display: none;
      }
      .main.show {
        display: block;
      }
      .siderbar {
        float: left;
        width: 600px;
        margin-left: -600px;
        margin-bottom: 20px;
        padding-top: 60px;
      }
      .result {
        line-height: 1.3;
        font-size: 13px;
        font-family: monospace;
        border: 1px solid #006eff;
        margin: 0;
        height: 200px;
        overflow: auto;
        box-sizing: border-box;
        padding: 5px;
      }
      h1 {
        font-weight: normal;
        color: #333;
      }
      a {
        color: #006eff;
        background-color: transparent;
        padding: 8px 16px;
        line-height: 1.3;
        display: inline-block;
        text-align: center;
        margin: 0 8px 8px 0;
        border: 1px solid #006eff;
        font-size: 14px;
        text-decoration: none;
      }
      a:hover {
        color: #fff;
        background-color: #006eff;
      }
      hr {
        border: 0;
        border-top: 1px solid #006eff;
      }
      .demo-select-content {
        display: inline-block;
        font-size: 0;
        margin-left: 20px;
      }
      .demo-select-content div {
        display: inline-block;
        font-size: 16px;
        border: solid 1px #ddd;
        padding: 2px 6px;
        cursor: pointer;
      }
      .demo-select-content div.active {
        border-color: #006eff;
        color: #006eff;
      }
    </style>
  </head>
  <body>
    <div class="page">
      <h1>
        cos-js-sdk-v5
        <div class="demo-select-content">
          <div class="active" id="showCosDemo">cos demo</div>
          <div id="showCiDemo">ci demo</div>
        </div>
      </h1>
      <div class="main-wrap">
        <div class="main cos-main show"></div>
        <div class="main ci-main"></div>
      </div>
      <div class="siderbar">
        <pre class="result"></pre>
      </div>
    </div>

    <script src="../demo/common/beacon.min.js"></script>
    <script src="../demo/common/cls.min.js"></script>
    <script src="../dist/cos-js-sdk-v5.js"></script>
    <script src="./demo.js"></script>
    <script type="module" src="./CIDemos/index.js"></script>

    <script>
      (function () {
        var showCosDemoBtn = document.querySelector('#showCosDemo');
        var showCiDemobtn = document.querySelector('#showCiDemo');
        var cosMain = document.querySelector('.cos-main');
        var ciMain = document.querySelector('.ci-main');
        showCosDemoBtn.addEventListener('click', function (e) {
          showCosDemoBtn.className = 'active';
          showCiDemobtn.className = '';
          cosMain.className = 'main cos-main show';
          ciMain.className = 'main cos-main';
        });
        showCiDemobtn.addEventListener('click', function (e) {
          showCosDemoBtn.className = '';
          showCiDemobtn.className = 'active';
          cosMain.className = 'main cos-main';
          ciMain.className = 'main cos-main show';
        });

        // config 替换成自己的存储桶和账号信息
        var config = {
          Bucket: 'test-1250000000',
          Region: 'ap-guangzhou',
          Uin: '10001',
        };
        var getAuthorization = function (options, callback) {
          // 格式一、（推荐）后端通过获取临时密钥给到前端，前端计算签名
          // 服务端 JS 和 PHP 例子：https://github.com/tencentyun/cos-js-sdk-v5/blob/master/server/
          // 服务端其他语言参考 COS STS SDK ：https://github.com/tencentyun/qcloud-cos-sts-sdk
          var url = '/sts'; // 如果是 npm run sts.js 起的 nodejs server，使用这个
          var xhr = new XMLHttpRequest();
          xhr.open('POST', url, true);
          xhr.setRequestHeader('Content-Type', 'application/json');
          xhr.onload = function (e) {
            try {
              var data = JSON.parse(e.target.responseText);
              var credentials = data.credentials;
            } catch (e) {}
            if (!data || !credentials) {
              return logger.error('credentials invalid:\n' + JSON.stringify(data, null, 2));
            }
            callback({
              TmpSecretId: credentials.tmpSecretId,
              TmpSecretKey: credentials.tmpSecretKey,
              SecurityToken: credentials.sessionToken,
              StartTime: data.startTime, // 时间戳，单位秒，如：1580000000，建议返回服务器时间作为签名的开始时间，避免用户浏览器本地时间偏差过大导致签名错误
              ExpiredTime: data.expiredTime, // 时间戳，单位秒，如：1580000000
              ScopeLimit: true, // 细粒度控制权限需要设为 true，会限制密钥只在相同请求时重复使用
            });
          };
          xhr.send(JSON.stringify(options.Scope));

          // // 格式二、（推荐）【细粒度控制权限】后端通过获取临时密钥给到前端，前端只有相同请求才重复使用临时密钥，后端可以通过 Scope 细粒度控制权限
          // // 服务端例子：https://github.com/tencentyun/qcloud-cos-sts-sdk/edit/master/scope.md
          // // var url = '../server/sts.php'; // 如果起的是 php server 用这个
          // var url = '/sts-scope'; // 如果是 npm run sts.js 起的 nodejs server，使用这个
          // var xhr = new XMLHttpRequest();
          // xhr.open('POST', url, true);
          // xhr.setRequestHeader('Content-Type', 'application/json');
          // xhr.onload = function (e) {
          //     try {
          //         var data = JSON.parse(e.target.responseText);
          //         var credentials = data.credentials;
          //     } catch (e) {
          //     }
          //     if (!data || !credentials) {
          //         return logger.error('credentials invalid:\n' + JSON.stringify(data, null, 2))
          //     };
          //     callback({
          //         TmpSecretId: credentials.tmpSecretId,
          //         TmpSecretKey: credentials.tmpSecretKey,
          //         SecurityToken: credentials.sessionToken,
          //         StartTime: data.startTime, // 时间戳，单位秒，如：1580000000，建议返回服务器时间作为签名的开始时间，避免用户浏览器本地时间偏差过大导致签名错误
          //         ExpiredTime: data.expiredTime, // 时间戳，单位秒，如：1580000000
          //         ScopeLimit: true, // 细粒度控制权限需要设为 true，会限制密钥只在相同请求时重复使用
          //     });
          // };
          // xhr.send(JSON.stringify(options.Scope));

          // // 格式三、（不推荐，分片上传权限不好控制）前端每次请求前都需要通过 getAuthorization 获取签名，后端使用固定密钥或临时密钥计算签名返回给前端
          // // 服务端获取签名，请参考对应语言的 COS SDK：https://cloud.tencent.com/document/product/436/6474
          // // 注意：这种有安全风险，后端需要通过 method、pathname 严格控制好权限，比如不允许 put / 等
          // var method = (options.Method || 'get').toLowerCase();
          // var query = options.Query || {};
          // var headers = options.Headers || {};
          // var pathname = options.Pathname || '/';
          // // var url = 'http://127.0.0.1:3000/auth';
          // var url = '../server/auth.php';
          // var xhr = new XMLHttpRequest();
          // var data = {
          //     method: method,
          //     pathname: pathname,
          //     query: query,
          //     headers: headers,
          // };
          // xhr.open('POST', url, true);
          // xhr.setRequestHeader('content-type', 'application/json');
          // xhr.onload = function (e) {
          //     try {
          //         var data = JSON.parse(e.target.responseText);
          //     } catch (e) {
          //     }
          //     if (!data || !data.authorization) return console.error('authorization invalid');
          //     callback({
          //         Authorization: data.authorization,
          //         // SecurityToken: data.sessionToken, // 如果使用临时密钥，需要把 sessionToken 传给 SecurityToken
          //     });
          // };
          // xhr.send(JSON.stringify(data));

          // // 格式四、（不推荐，适用于前端调试，避免泄露密钥）前端使用固定密钥计算签名
          // var authorization = COS.getAuthorization({
          //     SecretId: 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx', // 可传固定密钥或者临时密钥
          //     SecretKey: 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx', // 可传固定密钥或者临时密钥
          //     Method: options.Method,
          //     Pathname: options.Pathname,
          //     Query: options.Query,
          //     Headers: options.Headers,
          //     Expires: 900,
          // });
          // callback({
          //     Authorization: authorization,
          //     // SecurityToken: credentials.sessionToken, // 如果使用临时密钥，需要传 SecurityToken
          // });
        };

        const clsClient = new ClsClient({
          topicId: 'xxxxxxx-xxxx-xxxx-xxxx-xxxxxxxx', // 日志主题 id
          region: 'ap-guangzhou', // 日志主题所在地域，比如 ap-guangzhou
          maxRetainDuration: 30, // 默认 30s
          maxRetainSize: 20, // 默认20条
        });

        var cos = new COS({
          getAuthorization: getAuthorization,
          UploadCheckContentMd5: true,
          // BeaconReporter: BeaconAction, // 开启灯塔上报
          // ClsReporter: clsClient,  // 开启 cls 上报
        });

        var util = {
          createFile: function (options) {
            var buffer = new ArrayBuffer(options.size || 0);
            var arr = new Uint8Array(buffer);
            [].forEach.call(arr, function (char, i) {
              arr[i] = 0;
            });
            var opt = {};
            options.type && (opt.type = options.type);
            var blob = new Blob([buffer], options);
            return blob;
          },
          selectLocalFile: function (onChange) {
            var id = 'file_selector';
            var input = document.createElement('input');
            input.style = 'width:0;height:0;border:0;margin:0;padding:0;';
            input.type = 'file';
            input.id = id;
            input.onchange = function (e) {
              var files = this.files;
              if (!files.length) return;
              onChange && onChange(files);
              document.body.removeChild(input);
            };
            document.body.appendChild(input);
            input.click();
          },
        };

        // 对更多字符编码的 url encode 格式
        var camSafeUrlEncode = function (str) {
          return encodeURIComponent(str)
            .replace(/!/g, '%21')
            .replace(/'/g, '%27')
            .replace(/\(/g, '%28')
            .replace(/\)/g, '%29')
            .replace(/\*/g, '%2A');
        };

        var pre = document.querySelector('.result');
        var showLogText = function (text, color) {
          if (typeof text === 'object') {
            try {
              text = JSON.stringify(text);
            } catch (e) {}
          }
          var div = document.createElement('div');
          div.innerText = text;
          color && (div.style.color = color);
          pre.appendChild(div);
          pre.style.display = 'block';
          pre.scrollTop = pre.scrollHeight;
        };

        var logger = {
          log: function (text) {
            console.log.apply(console, arguments);
            var args = [].map.call(arguments, function (v) {
              return typeof v === 'object' ? JSON.stringify(v, null, 2) : v;
            });

            var logStr = args.join(' ');

            if (logStr.length > 1000000) {
              logStr =
                logStr.slice(0, 1000000) + '...content is too long, the first 1000000 characters are intercepted';
            }

            showLogText(logStr);
          },
          error: function (text) {
            console.error(text);
            showLogText(text, 'red');
          },
        };

        /**
         * 这里demo为了方便挂在了window上 实际使用请结合项目比如可使用模块导出
         * */
        window.config = config;
        window.cos = cos;
        window.util = util;
        window.logger = logger;
        window.camSafeUrlEncode = camSafeUrlEncode;
      })();
    </script>
  </body>
</html>
